package com.wiscamp.ninechapters.problems.domain.services;

import com.wiscamp.ninechapters.problems.domain.ProblemsErrorCodes;
import com.wiscamp.ninechapters.problems.domain.models.types.QuestionType;
import com.wiscamp.ninechapters.problems.domain.repositories.QuestionTypeRepository;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.BaseDomainService;
import cube.ddd.exception.ExceptionUtils;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * Problem Type Service
 *
 * @author yifeng
 */
@Service
public class QuestionTypeService extends BaseDomainService {

    private final QuestionTypeRepository questionTypeRepository;

    private final String CACHE_NAME = "questionTypes";

    public QuestionTypeService(QuestionTypeRepository questionTypeRepository) {
        this.questionTypeRepository = questionTypeRepository;
    }

    /**
     * Gets a question type
     *
     * @param typeId
     * @return
     */

    @Cacheable(value = CACHE_NAME, key = "#typeId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public QuestionType getQuestionType(@Min(0) long typeId) {
        var questionType = questionTypeRepository.getQuestionType(typeId);
        if (Objects.isNull(questionType)) {
            ExceptionUtils.throwServiceException(ProblemsErrorCodes.QUESTION_TYPE_NOT_FOUND, typeId);
        }
        return questionType;
    }

    /*@HandleServiceException
    public QuestionType getQuestionTypeByCode(@NotBlank String code) {
        return questionTypeRepository.getQuestionTypeByCode(code);
    }

    @HandleServiceException
    public Collection<QuestionType> getQuestionTypesByName(@NotBlank String name) {
        return questionTypeRepository.getQuestionTypesByName(name);
    }

    @HandleServiceException
    public Collection<QuestionType> getAvailableQuestionTypes() {
        return questionTypeRepository.getAvailableQuestionTypes();
    }*/

    /**
     * Creates a question type
     *
     * @param questionType
     * @return
     */
    @CachePut(value = CACHE_NAME, key = "#questionType.typeId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public QuestionType createQuestionType(@NotNull QuestionType questionType, long operatorId) {
        var existedQuestionType = questionTypeRepository.getQuestionTypeByCode(questionType.getTypeCode());
        if (Objects.nonNull(existedQuestionType)) {
            ExceptionUtils.throwServiceException(ProblemsErrorCodes.QUESTION_TYPE_CODE_EXISTS, questionType);
        }

        questionType.createBy(operatorId);
        return questionTypeRepository.saveQuestionType(questionType);
    }

    /**
     * Updates a question type
     *
     * @param questionType
     * @return
     */

    @CachePut(value = CACHE_NAME, key = "#questionType.typeId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    @HandleServiceException
    public QuestionType updateQuestionType(@NotNull QuestionType questionType, long operatorId) {
        var existedQuestionType = getQuestionType(questionType.getTypeId());
        existedQuestionType = questionTypeRepository.getQuestionTypeByCode(questionType.getTypeCode());
        if (Objects.nonNull(existedQuestionType) && existedQuestionType.getTypeId() != questionType.getTypeId()
                && existedQuestionType.getTypeCode().equalsIgnoreCase(questionType.getTypeCode())) {
            ExceptionUtils.throwServiceException(ProblemsErrorCodes.QUESTION_TYPE_CODE_EXISTS, questionType);
        }
        questionType.updateBy(operatorId);
        return questionTypeRepository.saveQuestionType(questionType);
    }

    /**
     * Deletes a question type
     *
     * @param typeId
     * @return
     */

    @CacheEvict(value = CACHE_NAME, key = "#typeId")
    @HandleServiceException
    public boolean deleteQuestionType(@Min(0) long typeId, long operatorId) {
        var questionType = getQuestionType(typeId);
        if (Objects.isNull(questionType)) return false;
        // 记录操作日志
        questionType.delete();
        questionType.updateBy(operatorId);
        questionTypeRepository.saveQuestionType(questionType);
        return true;
    }

    @CacheEvict(value = CACHE_NAME, key = "#typeId")
    @HandleServiceException
    public boolean enableQuestionType(@Min(0) long typeId, long operatorId) {
        var questionType = getQuestionType(typeId);
        if (Objects.isNull(questionType)) return false;
        // 记录操作日志
        questionType.enable();
        questionType.updateBy(operatorId);
        questionTypeRepository.saveQuestionType(questionType);
        return true;
    }

    @CacheEvict(value = CACHE_NAME, key = "#typeId")
    @HandleServiceException
    public boolean disableQuestionType(@Min(0) long typeId, long operatorId) {
        var questionType = getQuestionType(typeId);
        if (Objects.isNull(questionType)) return false;
        // 记录操作日志
        questionType.disable();
        questionType.updateBy(operatorId);
        questionTypeRepository.saveQuestionType(questionType);
        return true;
    }

}
